package org.oslims.client.uicomponents.inputfields;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.VerticalPanel;

public class SelectManyBox<T> extends Composite {

	final VerticalPanel mainPanel = new VerticalPanel();

	final HorizontalPanel panel = new HorizontalPanel();
	final ListBox unselectedItemBox = new ListBox(true);
	final ListBox selectedItemBox = new ListBox(true);
	final VerticalPanel buttonColumn = new VerticalPanel();
	final Button selectOne = new Button();
	final Button selectAll = new Button();
	final Button removeOne = new Button();
	final Button removeAll = new Button();
	final Label captation = new Label();

	private Map<String, T> unselectedItems = new HashMap<String, T>();
	private Map<String, T> selectedItems = new HashMap<String, T>();

	public SelectManyBox(String captation) {

		this.captation.setText(captation);
		mainPanel.add(this.captation);

		panel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);

		unselectedItemBox.setVisibleItemCount(10);
		unselectedItemBox.setWidth("8em");
		selectedItemBox.setVisibleItemCount(10);
		selectedItemBox.setWidth("8em");

		panel.add(unselectedItemBox);

		selectOne.setText(">");
		selectOne.addClickHandler(selectOneClicked);
		selectAll.setText(">>");
		selectAll.addClickHandler(selectAllClicked);
		removeAll.setText("<<");
		removeAll.addClickHandler(removeAllClicked);
		removeOne.setText("<");
		removeOne.addClickHandler(removeOneClicked);

		buttonColumn.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);

		buttonColumn.add(selectOne);
		buttonColumn.add(selectAll);
		buttonColumn.add(removeAll);
		buttonColumn.add(removeOne);

		panel.add(buttonColumn);

		panel.add(selectedItemBox);

		mainPanel.add(panel);

		initWidget(mainPanel);
	}

	public List<T> getSelectedItems() {
		List<T> selectedItems = new ArrayList<T>();

		for (T t : this.selectedItems.values()) {
			selectedItems.add(t);
		}

		return selectedItems;
	}

	public void selectAll() {
		while (unselectedItemBox.getItemCount() != 0) {
			selectedItemBox.addItem(unselectedItemBox.getItemText(0));
			selectedItems.put(unselectedItemBox.getItemText(0), unselectedItems.get(unselectedItemBox.getItemText(0)));

			unselectedItems.remove(unselectedItemBox.getItemText(0));
			unselectedItemBox.removeItem(0);
		}
	}

	public void unselectAll() {
		while (selectedItemBox.getItemCount() != 0) {
			unselectedItemBox.addItem(selectedItemBox.getItemText(0));

			unselectedItems.put(selectedItemBox.getItemText(0), selectedItems.get(selectedItemBox.getItemText(0)));

			selectedItems.remove(selectedItemBox.getItemText(0));
			selectedItemBox.removeItem(0);
		}
	}

	public void setItems(Collection<T> unselectedItems, Collection<T> selectedItems) {
		selectedItemBox.clear();
		this.selectedItems.clear();
		unselectedItemBox.clear();
		this.unselectedItems.clear();

		for (T s : unselectedItems) {
			this.unselectedItems.put(s.toString(), s);
			unselectedItemBox.addItem(s.toString());
		}

		for (T s : selectedItems) {
			this.selectedItems.put(s.toString(), s);
			selectedItemBox.addItem(s.toString());
		}
	}

	private ClickHandler selectOneClicked = new ClickHandler() {

		@Override
		public void onClick(ClickEvent event) {
			int selectedIndex = unselectedItemBox.getSelectedIndex();
			while (selectedIndex != -1) {
				selectedItemBox.addItem(unselectedItemBox.getItemText(selectedIndex));

				selectedItems.put(unselectedItemBox.getItemText(selectedIndex), unselectedItems.get(unselectedItemBox.getItemText(selectedIndex)));

				unselectedItems.remove(unselectedItemBox.getItemText(selectedIndex));
				unselectedItemBox.removeItem(selectedIndex);

				selectedIndex = unselectedItemBox.getSelectedIndex();
			}
		}
	};

	private ClickHandler selectAllClicked = new ClickHandler() {

		@Override
		public void onClick(ClickEvent event) {
			selectAll();
		}
	};

	private ClickHandler removeAllClicked = new ClickHandler() {

		@Override
		public void onClick(ClickEvent event) {
			unselectAll();
		}
	};

	private ClickHandler removeOneClicked = new ClickHandler() {

		@Override
		public void onClick(ClickEvent event) {
			int selectedIndex = selectedItemBox.getSelectedIndex();
			while (selectedIndex != -1) {
				unselectedItemBox.addItem(selectedItemBox.getItemText(selectedIndex));

				unselectedItems.put(selectedItemBox.getItemText(selectedIndex), selectedItems.get(selectedItemBox.getItemText(selectedIndex)));

				selectedItems.remove(selectedItemBox.getItemText(selectedIndex));
				selectedItemBox.removeItem(selectedIndex);

				selectedIndex = selectedItemBox.getSelectedIndex();
			}
		}
	};
}
